package com.boarsoft.boar.oss.util;

import com.boarsoft.bean.ReplyInfo;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
 * @author tao.wang57
 * @desc 对象操作工具类<p>
 * @date 2023-03-25 pm
 */
public class ManagerObjectUtil {

    private static final Logger log = LoggerFactory.getLogger(ManagerObjectUtil.class);

    /**
     * 通过objectName删除对象
     *
     * @param obsClient
     * @param bucketName
     * @param objectName 对象名。对象名是对象在存储桶中的唯一标识。对象名是对象在桶中的完整路径，路径中不包含桶名。
     *                   例如，您对象的访问地址为examplebucket.obs.cn-north-4.myhuaweicloud.com/folder/test.txt 中，
     *                   对象名为folder/test.txt。
     * @return
     */
    public static ReplyInfo<Object> deleteByObjectName(ObsClient obsClient, String bucketName, String objectName) {
        try {
            // 删除单个对象
            obsClient.deleteObject(bucketName, objectName);
            log.info("deleteObject successfully");
        } catch (ObsException e) {
            log.error("deleteObject failed", e);
            printObsException(e);
        } catch (Exception e) {
            // 其他异常信息打印
            log.error("deleteObject failed", e);
        } finally {
            if (obsClient != null) {
                try {
                    obsClient.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return ReplyInfo.SUCCESS;
    }

    /**
     * 批量删除
     *
     * @param obsClient
     * @param bucketName
     * @param num        批量删除对象一次能接收最大对象数目为1000个，如果超出限制，服务端会返回请求不合法。
     * @return
     */
    public static ReplyInfo<Object> deleteBatch(ObsClient obsClient, String bucketName, int num) {
        try {
            // 批量删除对象
            ListVersionsRequest request = new ListVersionsRequest(bucketName);
            // 每次批量删除100个对象
            request.setMaxKeys(num);
            ListVersionsResult result = null;
            do {
                result = obsClient.listVersions(request);
                DeleteObjectsRequest deleteRequest = new DeleteObjectsRequest(bucketName);
                // deleteRequest.setQuiet(true); // 注意此demo默认是详细模式，如果要使用简单模式，请添加本行代码
                for (VersionOrDeleteMarker v : result.getVersions()) {
                    // 获取对象和版本号
                    deleteRequest.addKeyAndVersion(v.getKey(), v.getVersionId());
                }
                if (deleteRequest.getKeyAndVersions().length > 0) {
                    DeleteObjectsResult deleteResult = obsClient.deleteObjects(deleteRequest);
                    // 获取删除成功的对象
                    //System.out.println("DeletedObjectResults:" + deleteResult.getDeletedObjectResults());
                    // 获取删除失败的对象
                    //System.out.println("ErrorResults:" + deleteResult.getErrorResults());
                } else {
                    log.error("No object to delete");
                }
                request.setKeyMarker(result.getNextKeyMarker());
                // 如果没有开启多版本对象，就不需要设置VersionIdMarker
                request.setVersionIdMarker(result.getNextVersionIdMarker());
            } while (result.isTruncated());
            log.info("deleteObjects successfully");
        } catch (ObsException e) {
            log.error("deleteObjects failed", e);
            printObsException(e);
        } catch (Exception e) {
            // 其他异常信息打印
            log.error("deleteObjects failed", e);
        } finally {
            if (obsClient != null) {
                try {
                    obsClient.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return ReplyInfo.SUCCESS;
    }

    /**
     * 判断对象是否存在
     *
     * @param obsClient  obs客户端
     * @param bucketName 桶
     * @param objectName 对象名 如 对象名为folder/test.txt
     * @return
     */
    public static boolean exits(ObsClient obsClient, String bucketName, String objectName) {
        boolean result = Boolean.FALSE;
        try {
            // 判断指定的对象是否存在
            result = obsClient.doesObjectExist(bucketName, objectName);
            log.info("doesObjectExist successfully");
        } catch (ObsException e) {
            log.error("doesObjectExist failed", e);
            printObsException(e);
        } catch (Exception e) {
            // 其他异常信息打印
            log.error("doesObjectExist failed", e);
        } finally {
            if (obsClient != null) {
                try {
                    obsClient.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return result;
    }

    public static ReplyInfo<Object> listSimple(ObsClient obsClient, String bucketName) {
        ReplyInfo<Object> result = new ReplyInfo<Object>();
        ObjectListing list = null;
        try {
            // 简单列举
            list = obsClient.listObjects(bucketName);
            /*for (ObsObject obsObject : result.getObjects()) {
                System.out.println("listObjects successfully");
                System.out.println("ObjectKey:" + obsObject.getObjectKey());
                System.out.println("Owner:" + obsObject.getOwner());
            }*/
        } catch (ObsException e) {
            log.error("listObjects failed", e);
            printObsException(e);
        } catch (Exception e) {
            log.error("listObjects failed", e);
        } finally {
            if (obsClient != null) {
                try {
                    obsClient.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        result.setData(list);
        result.setSuccess(Boolean.TRUE);
        return result;
    }

    private static void printObsException(ObsException e) {
        // 请求失败,打印http状态码
        log.error("HTTP Code:" + e.getResponseCode());
        // 请求失败,打印服务端错误码
        log.error("Error Code:" + e.getErrorCode());
        // 请求失败,打印详细错误信息
        log.error("Error Message:" + e.getErrorMessage());
        // 请求失败,打印请求id
        log.error("Request ID:" + e.getErrorRequestId());
        log.error("Host ID:" + e.getErrorHostId());
    }
}
